package priv.pfz.qatool.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;


/**
 * Created by fangzhou.peng on 2016/12/20.
 * 表格工具，提供排序、以html输出、以csv输出、以excel输出等功能
 */
public class TableUtil {

    private List<String> titles = Lists.newArrayList();

    private List<List<Object>> content = Lists.newArrayList();

    public TableUtil() {
    }

    public TableUtil(List<String> titles) {
        this.titles = titles;
    }

    public static TableUtil create(List<String> titles) {
        return new TableUtil(titles);
    }

    public static TableUtil create(String... titles) {
        return create(Lists.newArrayList(titles));
    }

    public void setTitles(List<String> titles) {
        this.titles = titles;
    }

    public List<String> getTitles() {
        return titles;
    }

    public List<List<Object>> getContent() {
        return content;
    }

    public void setContent(List<List<Object>> content) {
        this.content = content;
    }

    public int rowSize() {
        return content.size();
    }

    /**
     * 添加一行到rowIndex处，缺少的格子会自动用null补齐
     *
     * @return 是否成功添加
     */
    public boolean addRowByIndex(int rowIndex, List<Object> row) {
        if (rowIndex < 0 || rowIndex > content.size()) {
            return false;
        }
        int rowSize = row.size();
        int titleSize = titles.size();
        for (int i = rowSize; i < titleSize; i++) {
            row.add(null);
        }
        this.content.add(rowIndex, row);
        return true;
    }

    public boolean addRowByIndex(int rowIndex, Object... objects) {
        return addRowByIndex(rowIndex, Lists.newArrayList(objects));
    }

    public boolean addRow(List<Object> row) {
        return addRowByIndex(content.size(), row);
    }

    public boolean addRow(Object... objects) {
        return addRowByIndex(content.size(), Lists.newArrayList(objects));
    }

    /**
     * 按自然方法排序
     *
     * @param colIndex 列下标（从0开始）
     * @param <T>      排序的类型
     */
    public <T extends Comparable> void sort(final int colIndex) {
        Collections.sort(content, Ordering.from(new Comparator<List<Object>>() {
            @Override
            public int compare(List<Object> o1, List<Object> o2) {
                return Ordering.<T>natural().nullsFirst().compare((T) o1.get(colIndex), (T) o2.get(colIndex));
            }
        }));
    }

    /**
     * 自定义排序
     *
     * @param colIndex   列下标（从0开始）
     * @param comparator 比较器
     */
    public void sort(final int colIndex, final Comparator comparator) {
        Collections.sort(content, new Comparator<List<Object>>() {
            @Override
            public int compare(List<Object> o1, List<Object> o2) {
                return comparator.compare(o1.get(colIndex), o2.get(colIndex));
            }
        });
    }

    public void clear() {
        this.content.clear();
    }

    public String getStringValue(int rowIndex, int colIndex) {
        if (rowIndex < 0 || rowIndex >= content.size() || colIndex < 0 || colIndex >= titles.size()) {
            return "";
        }
        return MoreObjects.firstNonNull(content.get(rowIndex).get(colIndex), "").toString();
    }

    public String toHtml() {
        StringBuilder sb = new StringBuilder();
        sb.append("<style type=\"text/css\" media=\"all\">td, th {padding: 3px;} </style>");
        //表头
        sb.append("<table border=\"1\" style=\"border-collapse:collapse;\"><thead><tr>");
        for (String title : titles) {
            sb.append("<th>" + title + "</th>");
        }
        sb.append("</tr></thead><tbody>");
        //内容
        for (int i = 0; i < content.size(); i++) {
            sb.append("<tr>");
            for (int j = 0; j < titles.size(); j++) {
                sb.append("<td>" + getStringValue(i, j) + "</td>");
            }
            sb.append("</tr>");
        }
        sb.append("</tbody></table>");
        return sb.toString();
    }

    public String toCsv() {
        StringBuilder sb = new StringBuilder();
        sb.append(Joiner.on(",").join(titles)).append("\n");
        for (List<Object> row : content) {
            sb.append(Joiner.on(",").useForNull("").join(row)).append("\n");
        }
        return sb.toString();
    }

    public HSSFWorkbook toExcel() {
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet();
        //create title
        HSSFRow titleRow = sheet.createRow(0);
        for (int i = 0; i < titles.size(); i++) {
            titleRow.createCell(i).setCellValue(titles.get(i));
        }
        //create content
        for (int i = 0; i < content.size(); i++) {
            HSSFRow contentRow = sheet.createRow(i + 1);
            for (int j = 0; j < titles.size(); j++) {
                contentRow.createCell(j).setCellValue(getStringValue(i, j));
            }
        }
        return workbook;
    }

    public void downloadExcel(String excelName, HttpServletResponse response) {
        try {
            response.setContentType("octets/stream");
            response.addHeader("Content-Disposition", "attachment;filename=" + new String(excelName.getBytes("gb2312"), "ISO8859-1") + ".xls");
            response.setCharacterEncoding("UTF-8");
            OutputStream out = response.getOutputStream();
            toExcel().write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public JSONArray toJsonArray() {
        JSONArray jsonArray = new JSONArray();
        for (List<Object> row : content) {
            JSONObject json = new JSONObject();
            for (int i = 0; i < row.size(); i++) {
                json.put(titles.get(i), row.get(i));
            }
            jsonArray.add(json);
        }
        return jsonArray;
    }

    public String toBootstrapTable() {
        StringBuilder sb = new StringBuilder();
        sb.append("<link rel=\"stylesheet\" href=\"//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.12.1/bootstrap-table.min.css\">");
        sb.append("<script src=\"//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.12.1/bootstrap-table.min.js\"></script>");
        sb.append("<script src=\"//cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.12.1/locale/bootstrap-table-zh-CN.min.js\"></script>");
        //表头
        sb.append("<table data-toggle=\"table\" data-pagination=\"true\" data-search=\"true\"><thead><tr>");
        for (String title : titles) {
            sb.append("<th data-sortable=\"true\">" + title + "</th>");
        }
        sb.append("</tr></thead><tbody>");
        //内容
        for (int i = 0; i < content.size(); i++) {
            sb.append("<tr>");
            for (int j = 0; j < titles.size(); j++) {
                sb.append("<td>" + getStringValue(i, j) + "</td>");
            }
            sb.append("</tr>");
        }
        sb.append("</tbody></table>");
        return sb.toString();
    }

}
